﻿using System;
using System.IO;
using System.Text.RegularExpressions;

namespace Common
{
    public class Part
    {
        const string XRegularExpression = @"X(-?(0|(\d*)|\.)(\.\d+)?)";
        const string YRegularExpression = @"Y(-?(0|(\d*)|\.)(\.\d+)?)";

        public int PartID;
        public float SmallestX;
        public float SmallestY;
        public float LargestX;
        public float LargestY;
        public float XSize;
        public float YSize;
        public float OffsetX;
        public float OffsetY;
        public string Filename;
        public string FilePath;
        public string OriginalGCodeFile;
        public string[] OriginalGCodeLines;
        public string[] OffsetGCodeLines;

        public Regex XRegExp = new Regex(XRegularExpression, RegexOptions.IgnoreCase);
        public Regex YRegExp = new Regex(YRegularExpression, RegexOptions.IgnoreCase);
        
        public Part(string filename)
        {
            OriginalGCodeFile = File.ReadAllText(filename);
            OriginalGCodeLines = OriginalGCodeFile.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

            // Set the filename...
            FilePath = Path.GetDirectoryName(filename);
            Filename = Path.GetFileName(filename);

            ParseGCode();
        }

        private void ParseGCode()
        {
            // Basically find the corners and the overall size of the file...
            float lSmallestX = 10000;
            float lSmallestY = 10000;
            float lLargestX = 0;
            float lLargestY = 0;

            foreach (string line in OriginalGCodeLines)
            {
                if (string.IsNullOrEmpty(line) == false)
                {
                    if ((line[0] != '(') && (line.Contains("G28") == false)) // Ignore Comments and G28...
                    {
                        // check for X or Y and if that number is the biggest or smallest then replace...
                        MatchCollection xMatchList = XRegExp.Matches(line);

                        if (xMatchList.Count > 0)
                        {
                            Match xMatch = xMatchList[0];

                            if (Convert.ToDouble(xMatch.Groups[1].Value) < lSmallestX)
                            {
                                lSmallestX = (float)Convert.ToDouble(xMatch.Groups[1].Value);
                            }

                            if (Convert.ToDouble(xMatch.Groups[1].Value) > lLargestX)
                            {
                                lLargestX = (float)Convert.ToDouble(xMatch.Groups[1].Value);
                            }
                        }

                        MatchCollection yMatchList = YRegExp.Matches(line);

                        if (yMatchList.Count > 0)
                        {
                            Match yMatch = yMatchList[0];

                            if (Convert.ToDouble(yMatch.Groups[1].Value) < lSmallestY)
                            {
                                lSmallestY = (float)Convert.ToDouble(yMatch.Groups[1].Value);
                            }

                            if (Convert.ToDouble(yMatch.Groups[1].Value) > lLargestY)
                            {
                                lLargestY = (float)Convert.ToDouble(yMatch.Groups[1].Value);
                            }
                        }
                    }
                }
            }

            SmallestX = lSmallestX;
            SmallestY = lSmallestY;
            LargestX = lLargestX;
            LargestY = lLargestY;
            XSize = LargestX - SmallestX;
            YSize = LargestY - SmallestY;
        }

        public void OffsetGCode(float xOffset, float yOffset)
        {
            OffsetX = xOffset;
            OffsetY = yOffset;

            foreach (string line in OriginalGCodeLines)
            {
                if (string.IsNullOrEmpty(line) == false)
                {
                    if ((line[0] != '(') && (line.Contains("G28") == false)) // Ignore Comments and G28...
                    {
                        // check for X or Y and if that number is the biggest or smallest then replace...
                        MatchCollection xMatchList = XRegExp.Matches(line);

                        if (xMatchList.Count > 0)
                        {
                            Match xMatch = xMatchList[0];

                            // replace the X value with the value plus the offset...
                            line.Replace(XRegularExpression, Convert.ToString(Convert.ToDouble(xMatch.Groups[1].Value) + OffsetX));
                        }

                        MatchCollection yMatchList = YRegExp.Matches(line);

                        if (yMatchList.Count > 0)
                        {
                            Match yMatch = yMatchList[0];

                            // Replace the Y value with the value plus the offset...
                            line.Replace(YRegularExpression, Convert.ToString(Convert.ToDouble(yMatch.Groups[1].Value) + OffsetY));

                        }
                    }
                }
            }

        }
    }
}
